package cn.kmsoft.jssc.service.processor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.*;
import cn.kmsoft.jssc.service.AnalyseTaskProcessor;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


/**
 * 土地规划的建设用地管制区-套合叠加分析
 * 
 * @author wangq
 *
 */
public class JsydgzqAnalyseTaskProcessor extends AnalyseTaskProcessor {
	private static final Logger logger = LoggerFactory.getLogger(JsydgzqAnalyseTaskProcessor.class);

	private final double areaScale=10000;
	//建设用地管制区
	private final String analysePoint="jsydgzq";//看配置文件
	private AnalyseTaskParam analyseTaskParam;
	private AnalyseConfig analyseConfig;
	
	public JsydgzqAnalyseTaskProcessor(AnalyseTaskParam param, AnalyseConfig analyseConfig) {
		this.analyseTaskParam=param;
		this.analyseConfig=analyseConfig; 
	}
	
	public AnalyseTaskParam getAnalyseTaskParam() {
		return analyseTaskParam;
	}
	public void setAnalyseTaskParam(AnalyseTaskParam analyseTaskParam) {
		this.analyseTaskParam = analyseTaskParam;
	}
	
	@Override
	public TaskResult call() throws Exception {
		// TODO Auto-generated method stub
		String threadId = Thread.currentThread().getName();
		
		String tableName = this.analyseTaskParam.getTableName();
		String analyseType=this.analyseTaskParam.getAnalystType();
		String dbKey = this.analyseTaskParam.getDbKey();
		int fgeo_wkid= this.analyseTaskParam.getFgeo_wkid();
		String feaTypePoint = analyseTaskParam.getFeaTypePoint();

		AnalyseDb analyseDb = this.analyseConfig.getAnalyseDbByDbkey(dbKey);
		if(analyseDb==null){
			System.out.println();
			String errorMsg = String.format("--->TaskProcessor stop, dbKey: %s, 为null",dbKey);
			System.out.println(errorMsg);
			logger.warn(errorMsg);

			return null;
		}
		String dbType = analyseDb.getDbType();
		String dbInstance = analyseDb.getDbInstance();
		String tablespace = analyseDb.getTablespace();
		String serverId = analyseDb.getServerId();//分析服务标识

		String tableId = dbInstance + "/" + tablespace + "." + tableName;

		//注意，根据数据库类型进行分类处置。
		//若为oracle的sde，则需要添加表空间；
		if("postgresql".equalsIgnoreCase(dbType)){
			//若为postgresql的postgis库，则去掉表空间或者为postgis_33_sample.sde.dltb_2018_500155_d36
			tableId = dbInstance + "/" + dbInstance+"."+ tablespace + "." + tableName;
		}
		String operatorMethod = "intersectpy";
		if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "intersectpy";
		}else if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "intersectpy2";
		}else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "spatialQuery";
		} else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "spatialQuery2";
		} else if(analyseType.equalsIgnoreCase("difference") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "difference";
		}

		AnalyseServer analyseServer = this.analyseConfig.getAnalyseServerByServerId(serverId);
		String serverUrl = analyseServer.getServerUrl();

		String targetUrl = serverUrl + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + analystType + "/" + tableId;
		//String tableId = this.analyseConfig.getDbInstance() + "/" + this.analyseConfig.getDbTablespace() + "." + tableName;
		//String targetUrl = this.analyseConfig.getAnalystServer() + "/" + analystType + "/" + tableId;
		//String targetUrl = this.analyseConfig.getAnalystServiceUriMap().get(this.analysePoint);

		//任务参数
		AnalyseTaskParam params = this.analyseTaskParam;
		params.setTargetUrl(targetUrl);

		TaskResult taskResult = this.startAnalyse(operatorMethod,threadId, params);

		return taskResult;
	}
	
	/**
	 * start分析
	 * 
	 * TaskParam params  
	 * Return 
	 */
	@Override
	public TaskResult startAnalyse(String operatorMethod,String threadId, AnalyseTaskParam params) {
		TaskResult result = new TaskResult();
		
		String targetUrl = params.getTargetUrl();
		String jobId = params.getJobId();
		String taskId = params.getTaskId();
		String dkbh = params.getDkbh();
		String tableName = params.getTableName();
		GeoJsonQuery query = (GeoJsonQuery) params.getQuery();
		
		result.setThreadId(threadId);
		result.setJobId(jobId);
		result.setTableName(tableName);
		//result.setAnalystPoint(this.analysePoint);
		result.setAnalystPoint(params.getAnalysePoint());
		result.setProcessorName(params.getProcessName());
		result.setTaskId(taskId);
		result.setDkbh(dkbh);

		System.out.println(String.format("--->doAnalyse,threadId: %s, jobId: %s,dkbh: %s,  targetUrl: %s",threadId, jobId, dkbh, targetUrl));
		//叠加分析
		List<JsydgzqDetailResult> jsydgzqDetailResultList= this.doJsydgzqAnalyse(jobId,targetUrl,query);
		
		Map<String, Statis03Result> jsydgzq03StatisResultMap = this.summaryJsydgzqStatis03Result(jsydgzqDetailResultList);
		List<GhtzGzq> ghtzGzqResults = this.convert2GhtzGzqList(taskId, dkbh, jsydgzq03StatisResultMap);
		
		System.out.println(String.format("--->threadId: %s, jobId: %s, analysePoint: %s, 叠加管制区后获得的三级分类数量： %d", threadId,jobId,this.analysePoint,ghtzGzqResults.size()));
		
		JsydgzqSummary01Result gzqSummary = this.summaryJsydgzqStatis01Result(jsydgzq03StatisResultMap);

		result.setDetailsListResult(jsydgzqDetailResultList);
	    result.setSummary03Result(jsydgzq03StatisResultMap);
	    result.setSummary03DBEntResult(ghtzGzqResults);
	    result.setSummary02Result(null);
	    result.setSummary01Result(gzqSummary);
	    
		return result;
	}
	
	/**
	 * 基本农田-叠加分析
	 * 
	 * @param query
	 * @return
	 */
	public List<JsydgzqDetailResult> doJsydgzqAnalyse(String jobId, String targetUrl, GeoJsonQuery query) {

		List<JsydgzqDetailResult> jsydgzqDetailResultList= new ArrayList<JsydgzqDetailResult>();
		
		String queryJsonStr = JSONObject.toJSONString(query);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		
		HttpEntity<String> entity = new HttpEntity<>(queryJsonStr, headers);
		
		//2、转发空间分析的请求
		ResponseEntity<JSONObject> exchange = this.exchangeSpatialAnalyst(jobId,targetUrl, entity);
		JSONObject gzqObject= exchange.getBody();
		if(gzqObject==null || gzqObject.getJSONArray("result")==null) {
			return jsydgzqDetailResultList;
		}
	
		/*
		List<GeoJsonFeature> geoFeatures = JSONObject.parseArray(gzqObject.getJSONArray("result").getJSONObject(0).getJSONArray("features").toJSONString(),GeoJsonFeature.class);
		int count = geoFeatures.size();
		for(int i=0; i<count;i++ ) {
			GeoJsonFeature fea = geoFeatures.get(i);
			String gzqlxdm = fea.getProperties().get("GZQLXDM").toString();
			String gzqlxmc = "";
			if(fea.getProperties().get("GZQMC")!=null) {
				gzqlxmc = fea.getProperties().get("GZQMC").toString();
			}else {
				switch(gzqlxdm){
					case "010":
						gzqlxmc="允许建设区";
						break;
					case "020":
						gzqlxmc="有条件建设区";
						break;
					case "030":
						gzqlxmc="限制建设区";
						break;
					case "040":
						gzqlxmc="禁止建设区";
						break;
				}
			}
			
			JsydgzqDetailResult jsydgzqResult= new JsydgzqDetailResult();
			jsydgzqResult.setBsm(fea.getProperties().get("BSM").toString());
			
			jsydgzqResult.setGzqlxdm(gzqlxdm);
			jsydgzqResult.setGzqmc(gzqlxmc);
			jsydgzqResult.setGzqmj(Double.parseDouble(fea.getProperties().get("AREA").toString()));
			
			jsydgzqDetailResultList.add(jsydgzqResult);
		}
		*/
		
		JSONArray feasJSONArray = gzqObject.getJSONArray("result").getJSONObject(0).getJSONArray("features");
		List<Map<String,String>> allFeaProperties = this.parseFeaGeometryAndProperties(feasJSONArray);
		int feaCount = allFeaProperties.size();		
		for(int i=0; i<feaCount;i++ ) {
			Map<String,String> feaProps = allFeaProperties.get(i);

			//将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
			Map<String,String> feaPropsKeyLowercCase = new HashMap<>();
			feaProps.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));

			//1-目标图层的字段值
			String bsm = feaPropsKeyLowercCase.get("bsm")!=null?feaPropsKeyLowercCase.get("bsm").toString():"-1";//BSM
			String gzqlxdm = feaPropsKeyLowercCase.get("gzqlxdm")!=null? feaPropsKeyLowercCase.get("gzqlxdm").toString():"-1";//GZQLXDM
			//管制区类型名称
			String gzqlxmc = "";
			if( !StringUtil.isNullOrEmpty(feaPropsKeyLowercCase.get("gzqmc")) ) {
				gzqlxmc = feaPropsKeyLowercCase.get("gzqmc").toString();//GZQMC
			}else {
				switch(gzqlxdm){
					case "-1":
						gzqlxmc="未知";
						break;
					case "010":
						gzqlxmc="允许建设区";
						break;
					case "020":
						gzqlxmc="有条件建设区";
						break;
					case "030":
						gzqlxmc="限制建设区";
						break;
					case "040":
						gzqlxmc="禁止建设区";
						break;
				}
			}
			//2-追加的3个几何面积
			double area = Double.parseDouble(feaPropsKeyLowercCase.get("area").toString());//叠加后重叠范围的几何面积AREA
			double fgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("fgeoarea").toString());//目标图层（sde库）原图斑几何面积FGEOAREA
			double sgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("sgeoarea").toString());//上传图斑的几何面积SGEOAREA
			//3-叠加相交结果的几何图形
			String geomText = feaPropsKeyLowercCase.get("geom").toString();
			
			JsydgzqDetailResult jsydgzqResult= new JsydgzqDetailResult();
			jsydgzqResult.setFeaProps(feaProps);

			jsydgzqResult.setBsm(bsm);
			jsydgzqResult.setGzqlxdm(gzqlxdm);
			jsydgzqResult.setGzqmc(gzqlxmc);
			jsydgzqResult.setGzqmj(Math.abs(area));
			//2-后台新建的新面积字段
			jsydgzqResult.setArea(Math.abs(area));//叠加相交面积，核心成果
			jsydgzqResult.setFgeoarea(Math.abs(fgeoarea));//目标图层（sde库）原图斑几何面积
			jsydgzqResult.setSgeoarea(Math.abs(sgeoarea));//上传图斑几何面积
			jsydgzqResult.setGeomText(geomText);
			
			jsydgzqDetailResultList.add(jsydgzqResult);
		}

		return jsydgzqDetailResultList;
	}
	
	/**
	 * 将管制区的叠加结果转换为三级类实体对象
	 * 
	 * @param taskId
	 * @param dkbh
	 * @param gzqStatis03Results
	 * @return
	 */
	public List<GhtzGzq> convert2GhtzGzqList(String taskId, String dkbh, Map<String,Statis03Result> gzqStatis03Results) {
		List<GhtzGzq> ghtzGzqResults= new ArrayList<GhtzGzq>();
		//管制区类型代码
		Set<String> gzqlxdmSet = gzqStatis03Results.keySet();
		Iterator<String> iter = gzqlxdmSet.iterator();
		while(iter.hasNext()) {
			String gzqlxdm = iter.next();
			Statis03Result gzqStatis = gzqStatis03Results.get(gzqlxdm);
			
			GhtzGzq ghtzGzq = new GhtzGzq();
			ghtzGzq.setTaskId(taskId);
			ghtzGzq.setDkbh(dkbh);
			ghtzGzq.setGzqlxdm(gzqlxdm);
			ghtzGzq.setGzqmc(gzqStatis.getMc());
			ghtzGzq.setGzqmj(gzqStatis.getAnalyseArea());
			
			ghtzGzqResults.add(ghtzGzq);
		}
		
		return ghtzGzqResults;
	}
	
	public Map<String, Statis03Result> summaryJsydgzqStatis03Result(List<JsydgzqDetailResult> jsydgzqDetailResultList) {
		Map<String,Statis03Result> jsydgzqStatisResults = new HashMap<String,Statis03Result>();
		//汇总为三级分类统计
		Iterator<JsydgzqDetailResult> detailIter = jsydgzqDetailResultList.iterator();
		while (detailIter.hasNext()) {
			JsydgzqDetailResult jsydgzq = detailIter.next();
			String gzqlxdm = jsydgzq.getGzqlxdm();
			String gzqmc = jsydgzq.getGzqmc();
			Double area = jsydgzq.getGzqmj();

			if (jsydgzqStatisResults.containsKey(gzqlxdm)) {
				// 已有的面积
				Double areaOfSum = jsydgzqStatisResults.get(gzqlxdm).getAnalyseArea();
				jsydgzqStatisResults.get(gzqlxdm).setAnalyseArea(areaOfSum + area);
			} else {
				Statis03Result statisResult = new Statis03Result();
				statisResult.setDm(gzqlxdm);
				statisResult.setMc(gzqmc);
				statisResult.setAnalyseArea(area);

				jsydgzqStatisResults.put(gzqlxdm, statisResult);
			}
		}

		return jsydgzqStatisResults;
	}
	
	/**
	 * 建设用地管制区-汇总为三级类为一级/二级分类
	 * @param statisResultMap
	 * @return
	 */
	public JsydgzqSummary01Result summaryJsydgzqStatis01Result(Map<String,Statis03Result> statisResultMap) {
		List<String> gzqmcList = new ArrayList<String>();
		List<String> gzqMcAndMjList = new ArrayList<String>();
		
		JsydgzqSummary01Result gzqSummary=new JsydgzqSummary01Result();
		
		//管制区代码
		Set<String> gzqdmSet = statisResultMap.keySet();
		Iterator<String> iter = gzqdmSet.iterator();
		while(iter.hasNext()) {
			String gzqdm = iter.next();
			
			Statis03Result statisResult = statisResultMap.get(gzqdm);			
			String gzqmc = statisResult.getMc();
			double area = statisResult.getAnalyseArea();
			
			switch(gzqdm){
				case "-1":
					//数据未知异常
					gzqSummary.setSjwzmj(area);
					break;
				case "010":
					//"允许建设区;
					gzqSummary.setYxjsqmj(area);
					break;
				case "020":
					//"有条件建设区;
					gzqSummary.setYtjjsqmj(area);
					break;
				case "030":
					//限制建设区;
					gzqSummary.setXzjsqmj(area);				
					break;
				case "040":
					//禁止建设区;
					gzqSummary.setJzjsqmj(area);
					break;
			}
			String gzqMcAnMjStr = String.format("%s%.4f%s",gzqmc, area/this.areaScale,"公顷");
			
			gzqmcList.add(gzqmc);
			gzqMcAndMjList.add(gzqMcAnMjStr);
		}
		
		gzqSummary.setGzqmcsStr( StringUtils.join(gzqmcList,","));
		gzqSummary.setGzqmcAndmjStr(StringUtils.join(gzqMcAndMjList,","));
		
		return gzqSummary;
	}
	
}
